import _ from 'lodash'
import { onMounted } from 'vue'
import { watch, ref, nextTick } from 'vue'
import type { Ref } from 'vue'
import type { ElTable } from 'element-plus'

// 废弃。。。

// 表格懒加载
export default function useLazyLoad(
  tableModuleRef: Ref<InstanceType<typeof HTMLElement>>,
  elTableRef: Ref<InstanceType<typeof ElTable>>,
  sourceTableData: ITableDataItem[]
) {
  // 加载的表格数据
  const targetTableData = ref<ITableDataItem[]>([])

  // table 区域高度
  let clientHeight: number = 0
  // 初始加载数量
  let loadCount: number = 0
  // 上一次滚动的距离
  let lastScrollTop = 0
  // table 行高度
  let tableLineHeight: number = -1
  // 上一次复制到的起始索引
  let lastCopiedStartIndex = 0
  // 上一次复制到的结束索引
  let lastCopiedEndIndex = 0
  // 向上滚动的个数
  let totalScrollCount = 0
  // 跳过下一次因为设置滚动条的触发
  let skipNext = false

  // 初始化加载数据
  function initLoadTargetTableData() {
    if (sourceTableData.length < loadCount) {
      targetTableData.value.push(...sourceTableData)
      lastCopiedEndIndex = sourceTableData.length
    } else {
      targetTableData.value.push(...sourceTableData.slice(0, loadCount))
      lastCopiedEndIndex = loadCount
    }
  }

  // 滚动加载数据
  function scrollLoadTargetTableData(scrollTop: number) {
    if (skipNext) {
      skipNext = false
      return
    }

    // 本次滚动的值
    const differenceValue = scrollTop - lastScrollTop

    // 获取一行单元格的高度
    if (tableLineHeight === -1) {
      const el = tableModuleRef.value.querySelector(
        '.el-table__row'
      ) as HTMLElement

      if (!el) return
      tableLineHeight = el.offsetHeight
    }

    // 滚动的个数
    const scrollCount = Math.round(Math.abs(differenceValue) / tableLineHeight)

    if (scrollCount > 0) {
      // 上一次滚动的距离重新赋值
      lastScrollTop = scrollTop

      // 向上滚动: 去除头部,增加尾部
      if (differenceValue > 0) {
        let res: ITableDataItem[] = []

        if (lastCopiedEndIndex + scrollCount > sourceTableData.length) {
          res = sourceTableData.slice(lastCopiedEndIndex)
          lastCopiedEndIndex = sourceTableData.length
        } else {
          res = sourceTableData.slice(
            lastCopiedEndIndex,
            lastCopiedEndIndex + scrollCount
          )
          lastCopiedEndIndex = lastCopiedEndIndex + scrollCount
        }
        targetTableData.value.push(...res)

        totalScrollCount += res.length

        // 头部只留 10 个
        if (totalScrollCount > 10) {
          for (let i = 0; i < totalScrollCount - 10; i++) {
            targetTableData.value.shift()
            // 起始索引后移
            lastCopiedStartIndex++
          }

          // 滚动条上移
          elTableRef.value.setScrollTop(
            scrollTop - (totalScrollCount - 10) * tableLineHeight
          )

          // 上次滚动距离扣减
          lastScrollTop -= (totalScrollCount - 10) * tableLineHeight

          skipNext = true
          // 余量为 10
          totalScrollCount = 10
        }
      } else {
        // 向下滚动: 去除尾部,增加头部
        let res: ITableDataItem[] = []

        if (lastCopiedStartIndex <= 0) return

        if (lastCopiedStartIndex - scrollCount <= 0) {
          res = sourceTableData.slice(0, lastCopiedStartIndex)
          lastCopiedStartIndex = 0
        } else {
          res = sourceTableData.slice(
            lastCopiedStartIndex - scrollCount,
            lastCopiedStartIndex
          )
          lastCopiedStartIndex = lastCopiedStartIndex - scrollCount
        }

        // 添加在数组开头
        targetTableData.value.unshift(...res)

        // 减去滚下来的元素,加上补充的元素
        totalScrollCount = totalScrollCount - scrollCount + res.length

        // 去除尾部元素
        for (let i = 0; i < res.length; i++) {
          targetTableData.value.pop()
          lastCopiedEndIndex--
        }

        // 滚动条回滚
        elTableRef.value.setScrollTop(scrollTop + res.length * tableLineHeight)

        // 上次滚动距离增加
        lastScrollTop += res.length * tableLineHeight

        skipNext = true
      }
    }
  }

  const handleTableScroll = _.debounce(
    ({ scrollTop }) => {
      scrollLoadTargetTableData(scrollTop)
    },
    100,
    {
      leading: true,
      // 最后必触发一次
      trailing: true
    }
  )

  watch(
    // 监听 tableData 长度的变化
    () => sourceTableData.length,
    async () => {
      await nextTick()
      // 初始化
      initLoadTargetTableData()
    },
    {
      immediate: true,
      once: true
    }
  )

  onMounted(() => {
    // 内容区高度
    clientHeight = tableModuleRef.value.clientHeight
    // (内容区高度 / 单行元素的最小高度) + 10: 下滚动留 10 的余量
    loadCount = Math.ceil(clientHeight / 40) + 10
  })

  return {
    targetTableData,
    handleTableScroll
  }
}
